home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Cache / Container / mdb.php < prev    next >
PHP Script  |  2004-10-01  |  14KB  |  381 lines

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PEAR :: Cache :: MDB Container                                       |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1997-2003 The PHP Group                                |
  6. // +----------------------------------------------------------------------+
  7. // | This source file is subject to version 2.0 of the PHP license,       |
  8. // | that is bundled with this package in the file LICENSE, and is        |
  9. // | available at through the world-wide-web at                           |
  10. // | http://www.php.net/license/2_02.txt.                                 |
  11. // | If you did not receive a copy of the PHP license and are unable to   |
  12. // | obtain it through the world-wide-web, please send a note to          |
  13. // | license@php.net so we can mail you a copy immediately.               |
  14. // +----------------------------------------------------------------------+
  15. // | Note: This is a MDB-oriented rewrite of Cache/Container/db.php.      |
  16. // | Thanks to Lukas Smith for his patience in answering my questions     |
  17. // +----------------------------------------------------------------------+
  18. // | Author: Lorenzo Alberton <l.alberton at quipo.it>                    |
  19. // +----------------------------------------------------------------------+
  20. //
  21. // $Id: mdb.php,v 1.3 2003/01/04 11:54:46 mj Exp $
  22.  
  23. require_once 'MDB.php';
  24. require_once 'Cache/Container.php';
  25.  
  26. /**
  27. * PEAR/MDB Cache Container.
  28. *
  29. * NB: The field 'changed' has no meaning for the Cache itself. It's just there
  30. * because it's a good idea to have an automatically updated timestamp
  31. * field for debugging in all of your tables.
  32. *
  33. * A XML MDB-compliant schema example for the table needed is provided.
  34. * Look at the file "mdb_cache_schema.xml" for that.
  35. *
  36. * ------------------------------------------
  37. * A basic usage example:
  38. * ------------------------------------------
  39. *
  40. * $dbinfo = array(
  41. *   'database'    => 'dbname',
  42. *   'phptype'     => 'mysql',
  43. *   'username'    => 'root',
  44. *   'password'    => '',
  45. *   'cache_table' => 'cache'
  46. * );
  47. *
  48. *
  49. * $cache = new Cache('mdb', $dbinfo);
  50. * $id = $cache->generateID('testentry');
  51. *
  52. * if ($data = $cache->get($id)) {
  53. *    echo 'Cache hit.<br />Data: '.$data;
  54. *
  55. * } else {
  56. *   $data = 'data of any kind';
  57. *   $cache->save($id, $data);
  58. *   echo 'Cache miss.<br />';
  59. * }
  60. *
  61. * ------------------------------------------
  62. *
  63. * @author   Lorenzo Alberton <l.alberton at quipo.it>
  64. * @version  $Id: mdb.php,v 1.3 2003/01/04 11:54:46 mj Exp $
  65. * @package  Cache
  66. */
  67. class Cache_Container_mdb extends Cache_Container {
  68.  
  69.     /**
  70.      * Name of the MDB table to store caching data
  71.      *
  72.      * @see  Cache_Container_file::$filename_prefix
  73.      */
  74.     var $cache_table = '';
  75.  
  76.     /**
  77.      * PEAR MDB object
  78.      *
  79.      * @var  object PEAR_MDB
  80.      */
  81.     var $db;
  82.  
  83.     /**
  84.      * Constructor
  85.      *
  86.      * @param mixed Array with connection info or dsn string
  87.      */
  88.     function Cache_Container_mdb($options)
  89.     {
  90.         $this->db = &MDB::Connect($options);
  91.         if(MDB::isError($this->db)) {
  92.            return new Cache_Error('MDB::connect failed: '
  93.                     . $this->db->getMessage(), __FILE__, __LINE__);
  94.         } else {
  95.             $this->db->setFetchMode(MDB_FETCHMODE_ASSOC);
  96.         }
  97.         $this->setOptions($options, array_merge($this->allowed_options,
  98.                                          array('dsn', 'cache_table')));
  99.     }
  100.  
  101.     /**
  102.      * Fetch in the db the data that matches input parameters
  103.      *
  104.      * @param    string  dataset ID
  105.      * @param    string  cache group
  106.      * @return   mixed   dataset value or NULL/Cache_Error on failure
  107.      * @access   public
  108.      */
  109.     function fetch($id, $group)
  110.     {
  111.         $query = 'SELECT cachedata FROM ' . $this->cache_table
  112.                 .' WHERE id='       . $this->db->getTextValue($id)
  113.                 .' AND cachegroup=' . $this->db->getTextValue($group);
  114.         if($res = $this->db->query($query)) {
  115.             if($this->db->endOfResult($res)) {
  116.                 //no rows returned
  117.                 $data = array(NULL, NULL, NULL);
  118.             } else {
  119.                 $clob = $this->db->fetchClob($res,0,'cachedata');
  120.                 if(!MDB::isError($clob)) {
  121.                     $cached_data = '';
  122.                     while(!$this->db->endOfLOB($clob)) {
  123.                         if(MDB::isError($error =
  124.                                     $this->db->readLob($clob,$data,8000)<0)) {
  125.                             return new Cache_Error('MDB::query failed: '
  126.                                     . $error->getMessage(), __FILE__, __LINE__);
  127.                         }
  128.                         $cached_data .= $data;
  129.                     }
  130.                     unset($data);
  131.                     $this->db->destroyLob($clob);
  132.                     $this->db->freeResult($res);
  133.  
  134.                     //finished fetching LOB, now fetch other fields...
  135.                     $query = 'SELECT userdata, expires FROM ' . $this->cache_table
  136.                             .' WHERE id='       . $this->db->getTextValue($id)
  137.                             .' AND cachegroup=' . $this->db->getTextValue($group);
  138.                     if($res = $this->db->query($query)) {
  139.                         $row = $this->db->fetchInto($res);
  140.                         if (is_array($row)) {
  141.                             $data = array(
  142.                                         $row['expires'],
  143.                                         $this->decode($cached_data),
  144.                                         $row['userdata']
  145.                                     );
  146.                         } else {
  147.                             $data = array(NULL, NULL, NULL);
  148.                         }
  149.                     } else {
  150.                         $data = array(NULL, NULL, NULL);
  151.                     }
  152.                 } else {
  153.                     return new Cache_Error('MDB::query failed: '
  154.                              . $clob->getMessage(), __FILE__, __LINE__);
  155.                 }
  156.             }
  157.             $this->db->freeResult($res);
  158.         } else {
  159.             //return new Cache_Error('MDB::query failed: '
  160.             //          . $result->getMessage(), __FILE__, __LINE__);
  161.             $data = array(NULL, NULL, NULL);
  162.         }
  163.  
  164.         // last used required by the garbage collection
  165.         $query = 'UPDATE '          . $this->cache_table
  166.                 .' SET changed='    . time()
  167.                 .' WHERE id='       . $this->db->getTextValue($id)
  168.                 .' AND cachegroup=' . $this->db->getTextValue($group);
  169.  
  170.         $res = $this->db->query($query);
  171.         if (MDB::isError($res)) {
  172.             return new Cache_Error('MDB::query failed: '
  173.                 . $this->db->errorMessage($res), __FILE__, __LINE__);
  174.         }
  175.         return $data;
  176.     }
  177.  
  178.    /**
  179.      * Stores a dataset in the database
  180.      *
  181.      * If dataset_ID already exists, overwrite it with new data,
  182.      * else insert data in a new record.
  183.      *
  184.      * @param    string  dataset ID
  185.      * @param    mixed   data to be cached
  186.      * @param    integer expiration time
  187.      * @param    string  cache group
  188.      * @param    string  userdata
  189.      * @access   public
  190.      */
  191.     function save($id, $data, $expires, $group, $userdata)
  192.     {
  193.         global $db;
  194.         $this->flushPreload($id, $group);
  195.  
  196.         $fields = array(
  197.             'id'        => array(
  198.                             'Type'   => 'text',
  199.                             'Value'  => $id,
  200.                             'Key'    => true
  201.                         ),
  202.             'userdata'  => array(
  203.                             'Type'   => 'integer',
  204.                             'Value'  => $userdata,
  205.                             'Null'   => ($userdata ? false : true)
  206.                         ),
  207.             'expires'   => array(
  208.                             'Type'   => 'integer',
  209.                             'Value'  => $this->getExpiresAbsolute($expires)
  210.                         ),
  211.             'cachegroup' => array(
  212.                             'Type'   => 'text',
  213.                             'Value'  => $group
  214.                         )
  215.             );
  216.  
  217.         $result = $this->db->replace($this->cache_table, $fields);
  218.  
  219.         if(MDB::isError($result)) {
  220.             //Var_Dump::display($result);
  221.             return new Cache_Error('MDB::query failed: '
  222.                     . $this->db->errorMessage($result), __FILE__, __LINE__);
  223.         }
  224.         unset($fields); //end first part of query
  225.         $query2 = 'UPDATE '   . $this->cache_table
  226.                  .' SET cachedata=?'
  227.                  .' WHERE id='. $this->db->getTextValue($id);
  228.  
  229.         if(($prepared_query = $this->db->prepareQuery($query2))) {
  230.             $char_lob = array(
  231.                             'Error' => '',
  232.                             'Type' => 'data',
  233.                             'Data' => $this->encode($data)
  234.                         );
  235.             if(!MDB::isError($clob = $this->db->createLob($char_lob))) {
  236.                 $this->db->setParamClob($prepared_query,1,$clob,'cachedata');
  237.                 if(MDB::isError($error=$this->db->executeQuery($prepared_query))) {
  238.                     return new Cache_Error('MDB::query failed: '
  239.                             . $error->getMessage() , __FILE__, __LINE__);
  240.                 }
  241.                 $this->db->destroyLob($clob);
  242.             } else {
  243.                 // creation of the handler object failed
  244.                 return new Cache_Error('MDB::query failed: '
  245.                         . $clob->getMessage() , __FILE__, __LINE__);
  246.             }
  247.             $this->db->freePreparedQuery($prepared_query);
  248.         } else {
  249.             //prepared query failed
  250.             return new Cache_Error('MDB::query failed: '
  251.                     . $prepared_query->getMessage() , __FILE__, __LINE__);
  252.         }
  253.     }
  254.  
  255.     /**
  256.      * Removes a dataset from the database
  257.      *
  258.      * @param    string  dataset ID
  259.      * @param    string  cache group
  260.      */
  261.     function remove($id, $group)
  262.     {
  263.         $this->flushPreload($id, $group);
  264.  
  265.         $query = 'DELETE FROM '     . $this->cache_table
  266.                 .' WHERE id='       . $this->db->getTextValue($id)
  267.                 .' AND cachegroup=' . $this->db->getTextValue($group);
  268.  
  269.         $res = $this->db->query($query);
  270.         if (MDB::isError($res)) {
  271.             return new Cache_Error('MDB::query failed: '
  272.                     . $this->db->errorMessage($res), __FILE__, __LINE__);
  273.         }
  274.     }
  275.  
  276.     /**
  277.      * Remove all cached data for a certain group, or empty
  278.      * the cache table if no group is specified.
  279.      *
  280.      * @param    string  cache group
  281.      */
  282.     function flush($group = '')
  283.     {
  284.         $this->flushPreload();
  285.  
  286.         if ($group) {
  287.             $query = 'DELETE FROM '       . $this->cache_table
  288.                     .' WHERE cachegroup=' . $this->db->getTextValue($group);
  289.         } else {
  290.             $query = 'DELETE FROM ' . $this->cache_table;
  291.         }
  292.  
  293.         $res = $this->db->query($query);
  294.         if (MDB::isError($res)) {
  295.             return new Cache_Error('MDB::query failed: '
  296.                 . $this->db->errorMessage($res), __FILE__, __LINE__);
  297.         }
  298.     }
  299.  
  300.     /**
  301.      * Check if a dataset ID/group exists.
  302.      *
  303.      * @param    string  dataset ID
  304.      * @param    string  cache group
  305.      * @return   boolean
  306.      */
  307.     function idExists($id, $group)
  308.     {
  309.         $query = 'SELECT id FROM '  . $this->cache_table
  310.                 .' WHERE id='       . $this->db->getTextValue($id)
  311.                 .' AND cachegroup=' . $this->db->getTextValue($group);
  312.         echo $query;
  313.         $res = $this->db->query($query);
  314.         if (MDB::isError($res)) {
  315.             return new Cache_Error('MDB::query failed: '
  316.                     . $this->db->errorMessage($res), __FILE__, __LINE__);
  317.         }
  318.         $row = $this->db->fetchInto($res);
  319.  
  320.         if (is_array($row)) {
  321.             return true;
  322.         } else {
  323.             return false;
  324.         }
  325.     }
  326.  
  327.     /**
  328.      * Garbage collector.
  329.      *
  330.      * @param    int maxlifetime
  331.      */
  332.     function garbageCollection($maxlifetime)
  333.     {
  334.         $this->flushPreload();
  335.         $query = 'DELETE FROM '        . $this->cache_table
  336.                 .' WHERE (expires <= ' . time()
  337.                 .' AND expires > 0) OR changed <= '. time() - $maxlifetime;
  338.  
  339.         $res = $this->db->query($query);
  340.  
  341.         $query = 'SELECT sum(length(cachedata)) as CacheSize FROM '
  342.                 . $this->cache_table;
  343.  
  344.         $cachesize = $this->db->getOne($query);
  345.         if (MDB::isError($cachesize)) {
  346.             return new Cache_Error('MDB::query failed: '
  347.                    . $this->db->errorMessage($cachesize), __FILE__, __LINE__);
  348.         }
  349.         //if cache is to big.
  350.         if ($cachesize > $this->highwater)
  351.         {
  352.             //find the lowwater mark.
  353.             $query = 'SELECT length(cachedata) as size, changed FROM '
  354.                     . $this->cache_table .' ORDER BY changed DESC';
  355.  
  356.             $res = $this->db->query($query);
  357.             if (MDB::isError($res)) {
  358.                return new Cache_Error('MDB::query failed: '
  359.                     . $this->db->errorMessage($res), __FILE__, __LINE__);
  360.             }
  361.             $numrows = $this->db->numRows($res);
  362.             $keep_size = 0;
  363.             while ($keep_size < $this->lowwater && $numrows--) {
  364.                 $entry = $this->db->fetchInto($res,MDB_FETCHMODE_ASSOC);
  365.                 $keep_size += $entry['size'];
  366.             }
  367.  
  368.             //delete all entries, which were changed before the "lowwater mark"
  369.             $query = 'DELETE FROM ' . $this->cache_table
  370.                     .' WHERE changed<='.($entry['changed'] ? $entry['changed'] : 0);
  371.  
  372.             $res = $this->db->query($query);
  373.             if (MDB::isError($res)) {
  374.                return new Cache_Error('MDB::query failed: '
  375.                     . $this->db->errorMessage($res), __FILE__, __LINE__);
  376.             }
  377.         }
  378.     }
  379.  
  380. }
  381. ?>